package com.niiwoo.civet.user.service.local;

import com.niiwoo.civet.user.dao.entity.MessageSendRecord;
import com.niiwoo.civet.user.dao.entity.MessageTemplate;
import com.niiwoo.civet.user.dao.entity.MessageTemplateExample;
import com.niiwoo.civet.user.dao.entity.UcAccount;
import com.niiwoo.civet.user.dao.mapper.MessageSendRecordMapperExt;
import com.niiwoo.civet.user.dao.mapper.MessageTemplateMapperExt;
import com.niiwoo.civet.user.dao.mapper.UserAccountMapperExt;
import com.niiwoo.civet.user.dto.UserAndContentDTO;
import com.niiwoo.civet.user.dto.UserAndParamsDTO;
import com.niiwoo.civet.user.enums.SmsSendStatusEnum;
import com.niiwoo.civet.user.enums.SmsSendTypeEnum;
import com.niiwoo.tripod.base.component.PrivacyMasks;
import com.niiwoo.tripod.service.component.SnowflakeIdWorker;
import com.niiwoo.tripod.sms.ISmsSendService;
import lombok.Getter;
import lombok.Setter;
import org.joda.time.DateTime;
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import java.util.Date;
import java.util.List;
import java.util.concurrent.CompletableFuture;

@Service
public class SendSmsLocalService {

    @Autowired
    private UserAccountMapperExt userAccountMapperExt;
    @Autowired
    private MessageTemplateMapperExt messageTemplateMapperExt;
    @Autowired
    private MessageSendRecordMapperExt messageSendRecordMapperExt;
    @Autowired
    private ISmsSendService iSmsSendService;
    @Autowired
    private PrivacyMasks privacyMasks;
    @Autowired
    private SnowflakeIdWorker snowflakeIdWorker;


    public void sendSms(List<UserAndParamsDTO> userAndParamsList, String templateKey, Date date) {
        sendSmsSynthetical(userAndParamsList,null,date);
    }


    public void sendSms(List<UserAndContentDTO> userAndContentList, Date date) {
        sendSmsSynthetical(null,userAndContentList,date);

    }


    private void sendSmsSynthetical(List<UserAndParamsDTO> userAndParamsList, List<UserAndContentDTO> userAndContentList, Date date){
        Date sendDate;
        if (date == null || date.before(DateTime.now().toDate())){
            sendDate = DateTime.now().toDate();
        }else {
            sendDate = date;
        }
        CompletableFuture.runAsync(() -> {
            long timestemp = System.currentTimeMillis();
            //引用Job Class
            JobDetail job = JobBuilder.newJob(SmsJobService.class)
                    .withIdentity("sendSms"+timestemp, "sms"+timestemp)
                    .withDescription("定时发送短信")
                    .build();

            //加入属性name到JobDataMap
            job.getJobDataMap().put("userAndParamsList", userAndParamsList);
            job.getJobDataMap().put("userAndContentList", userAndContentList);


            //定义一个SimpleTrigger
            Trigger trigger = TriggerBuilder.newTrigger()
                    .withIdentity("smsTrigger"+timestemp)
                    .withSchedule(SimpleScheduleBuilder.simpleSchedule())
                    .startAt(sendDate)
                    .build();
            try {
                Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
                scheduler.scheduleJob(job, trigger);

                scheduler.start();
            } catch (SchedulerException e) {
                e.printStackTrace();
            }
        });
    }


    public void sendSmsByMobileWithTempId(String mobileNo, Long tempId, List<Object> params) {
        MobileAndContent mobileAndContent = ((SendSmsLocalService) AopContext.currentProxy()).initSmsSendByMobile(mobileNo, tempId, params);
        doSend(mobileAndContent);
    }

    public void sendSmsByUserId(String userId, String templateKey, List<Object> params) {
        MobileAndContent mobileAndContent = ((SendSmsLocalService) AopContext.currentProxy()).initSmsSendByUserId(userId, templateKey, params);
        doSend(mobileAndContent);
    }

    public void sendSmsByMobile(String mobileNo, String content) {
        MobileAndContent mobileAndContent = ((SendSmsLocalService) AopContext.currentProxy()).initSmsSendByMobile(mobileNo, content);
        doSend(mobileAndContent);
    }

    public void sendSmsByMobile(String mobileNo, String templateKey, List<Object> params) {
        MobileAndContent mobileAndContent = ((SendSmsLocalService) AopContext.currentProxy()).initSmsSendByMobile(mobileNo,  initContent(templateKey, params));
        doSend(mobileAndContent);
    }

    public  void doSend(MobileAndContent mobileAndContent) {
        CompletableFuture.runAsync(() -> {
            sendSmsAsyn(mobileAndContent.getMobile(), mobileAndContent.getContent());
            updateSmsSendRecordToSended(mobileAndContent.getRecordId());
        });
    }

    private  void sendSmsAsyn(String mobile, String content) {
        iSmsSendService.send(mobile, content, null);
    }

    @Transactional
    public MobileAndContent initSmsSendByMobile(String mobileNo, String templateKey, List<Object> params) {
        //查询短信模板
        String content = initContent(templateKey, params);

        //插入短信发送记录
        Long recordId = insertMessageSendRecord(null, mobileNo, content);


        return buildMobileAndContent(mobileNo, content, recordId);
    }

    @Transactional
    public MobileAndContent initSmsSendByMobile(String mobileNo, Long templateId, List<Object> params) {
        //查询短信模板
        String content = initContent(templateId, params);

        //插入短信发送记录
        Long recordId = insertMessageSendRecord(null, mobileNo, content);


        return buildMobileAndContent(mobileNo, content, recordId);
    }

    @Transactional
    public MobileAndContent initSmsSendByUserId(String userId, String templateKey, List<Object> params) {
        //查找用户手机号
        UcAccount ucAccount = userAccountMapperExt.selectByPrimaryKey(userId);
        Assert.notNull(ucAccount, "用户手机号不存在");
        String mobile = privacyMasks.decryptPrivacy(ucAccount.getMobileNo());

        //查询短信模板
        String content = initContent(templateKey, params);

        //插入短信发送记录
        Long recordId = insertMessageSendRecord(userId, mobile, content);


        return buildMobileAndContent(mobile, content, recordId);
    }

    @Transactional
    public MobileAndContent initSmsSendByMobile(String mobileNo, String content) {
        //插入短信发送记录
        Long recordId = insertMessageSendRecord(null, mobileNo, content);


        return buildMobileAndContent(mobileNo, content, recordId);
    }

    @Transactional
    public String initContent(String templateKey, List<Object> params) {
        MessageTemplateExample example = new MessageTemplateExample();
        MessageTemplateExample.Criteria crit = example.createCriteria();
        crit.andTemplateKeyEqualTo(templateKey);
        List<MessageTemplate> messageTemplates = messageTemplateMapperExt.selectByExampleWithBLOBs(example);
        Assert.notEmpty(messageTemplates, "短信模板不存在");

        String content = CollectionUtils.isEmpty(params) ? messageTemplates.get(0).getTemplateContent() : String.format(messageTemplates.get(0).getTemplateContent(), params.toArray());
        return content;
    }

    @Transactional
    public String initContent(Long templateId, List<Object> params) {
        MessageTemplate messageTemplate = messageTemplateMapperExt.selectByPrimaryKey(templateId);
        Assert.notNull(messageTemplate, "短信模板不存在");

        String content = CollectionUtils.isEmpty(params) ? messageTemplate.getTemplateContent() : String.format(messageTemplate.getTemplateContent(), params.toArray());
        return content;
    }

    private MobileAndContent buildMobileAndContent(String mobileNo, String content, Long recordId) {
        MobileAndContent mobileAndContent = new MobileAndContent();
        mobileAndContent.setMobile(mobileNo);
        mobileAndContent.setContent(content);
        mobileAndContent.setRecordId(recordId);
        return mobileAndContent;
    }

    @Transactional
    public Long insertMessageSendRecord(String userId, String mobileNo, String content) {
        MessageSendRecord messageSendRecord = new MessageSendRecord();
        messageSendRecord.setTargetUserId(userId);
        messageSendRecord.setContent(content);
        messageSendRecord.setTargetMobileNo(privacyMasks.encryptPrivacy(mobileNo));
        messageSendRecord.setSendType(SmsSendTypeEnum.SEND_NOW.getValue());
        messageSendRecord.setSendStatus(SmsSendStatusEnum.NOTSEND.getValue());
        messageSendRecord.setId(snowflakeIdWorker.nextId());
        Date date = DateTime.now().toDate();

        messageSendRecord.setCreateTime(date);
        messageSendRecord.setSendTime(date);
        messageSendRecordMapperExt.insertSelective(messageSendRecord);
        return messageSendRecord.getId();
    }


    @Transactional
    public void updateSmsSendRecordToSended(Long id) {
        MessageSendRecord messageSendRecord = new MessageSendRecord();
        messageSendRecord.setId(id);
        messageSendRecord.setSendStatus(SmsSendStatusEnum.SENDED.getValue());
        messageSendRecordMapperExt.updateByPrimaryKeySelective(messageSendRecord);
    }

    @Getter
    @Setter
    static class MobileAndContent {
        private String mobile;
        private String content;
        private Long recordId;
    }







}
